import type { RedisCacheService } from '@/common/redis/redis-cache.service'

interface CacheableOptions {
  key: (...args: any[]) => string
  ttl?: number
}

export function Cacheable(options: CacheableOptions) {
  return (
    /** 方法所属类 */
    target: any,
    /** 方法名 */
    propertyKey: string,
    /** 方法函数 descriptor.value */
    descriptor: PropertyDescriptor,
  ) => {
    const originalMethod = descriptor.value

    descriptor.value = async function (...args: any[]) {
      const cacheService: RedisCacheService = this.cache
      const key = options.key(...args)
      const ttl = options.ttl ?? 3600

      const cached = await cacheService.get(key)
      if (cached) {
        return JSON.parse(cached)
      }

      // 调用原本的方法
      const result = await originalMethod.apply(this, args)
      await cacheService.set(key, JSON.stringify(result), ttl)
      return result
    }
  }
}

/*
async getUserById(id: string): Promise<User> {
  const cacheKey = `user:${id}`;
  const cached = await this.redis.get(cacheKey);
  if (cached) return JSON.parse(cached);

  const user = await this.db.findUserById(id);
  await this.redis.set(cacheKey, JSON.stringify(user), 'EX', 3600);
  return user;
}

⬇️⬇️⬇️⬇️⬇️⬇️

@Cacheable({ key: (id) => `user:${id}`, ttl: 3600 })
async getUserById(id: string): Promise<User> {
  return this.db.findUserById(id);
}
*/
